
% User: Armin Jalili
%
% Department of Electrical and Computer Engineering
% Isfahan University of Technology
% Updated by Armin Jalili
% Fri June 14 2013
%

vRef = 1;
NOB = 10;
scale = 2 * ( vRef / 2 ^ NOB );
% Generate the test signal 
v_osp = 0;
v_osn = 0;
lambda = 0;
NOS = 5e6; % increase for better accuracy! (higher ENOB_A)
N_tri = 1000;
    vCharge = Trigen(lambda, N_tri, 2 * vRef, v_osp, v_osn);
    vCharge = repmat(vCharge, 1, NOS / N_tri); % a bit slow
% Generate the input signal of the DAC
fIn = 67.37e6;
t_end = 1e-3;
%t = linspace(0, t_end, NOS); % a bit slow...
    t = 0 : t_end / ( NOS - 1) : t_end;
    vIn = 0.5 * sin( 2 * pi * fIn * t) + 0.5;
    decIn = fix( vIn * ( 2 ^ NOB - 1 ) );
%
% Apply the input signal to the DAC
% Determine the error parameters
sigmaDacGain = 0.03; %0.0 for ideal case
sigmaDacOff  = 0.035; %0.0 for ideal case
dacBinVector = (2.^(((NOB-1):-1:0) + sigmaDacGain * randn(1,NOB) )');
% For the time being, we assume dacOffset >= -1, otherwise we need to
% develop the calibration technique for such cases...
dacOffset    = -vRef*(1 - abs(sigmaDacOff * randn(1,1))) + scale / 2;
errit = [dacBinVector; dacOffset];

    anaOut = Dac(decIn, vRef, NOB, errit);
%
% Apply the output of the DAC and the test signal to the comparator
os_comp = 0; %(15e-3) * randn;
PN = ones(1 , NOS); %randn(1 , NOS) > 0;
    DigOut = Comp(vCharge, anaOut, os_comp, PN);
%
% Now perform the calibration: Estimate the errors etc
% 
    for i = NOB - 1 : -1 : 0
        P = decIn == 2 ^ i;
        N1 = sum( P .* DigOut );
        vDac(NOB - i) = (1 - 2 * N1 / sum(P)) * vRef;
    end
% Calculate the offset of the DAC
    P = decIn == 0;
    N1 = sum( P .* DigOut );
    vOs = (1 - 2 * N1 / sum(P)) * vRef;
%
% Estimate the bin vector
    scale     = 2*(vRef / (2^NOB));
    binVector = ( vDac - vOs ) / scale;

% Let's see some FFT results before and after calibration stuff...
    EstVector = [binVector vOs];
    IdealVector = [ 2.^((NOB-1):-1:0) -vRef + scale / 2];
    ErrVector = IdealVector - EstVector;
    CalVector = errit' + ErrVector;
%
N_ = 2 ^ 14;
fbin = 31;
vIn_ = 0.5 * sin( 2 * pi * fbin / N_ * [0:N_-1] ) + 0.5;
decIn_ = fix( vIn_ * ( 2 ^ NOB - 1 ) );
% Before calibration
    subplot(2,1,1);
    anaOut_ = Dac(decIn_, vRef, NOB, errit);
    ENOB_B = FFTII(anaOut_)
% After calibration
    subplot(2,1,2);
    anaOut_ = Dac(decIn_, vRef, NOB, CalVector);
    ENOB_A = FFTII(anaOut_)
